﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Windows.Browser;
using System.Collections.ObjectModel;
using System.Linq;

namespace SuperDeepZoom
{
    /// <summary>
    /// Manages fly through passed in from URL and also records fly through steps as the user navigates around the MSI
    /// which can then be serialised in to a new URL
    /// </summary>
    internal class FlyThroughManager : IDisposable
    {
        ObservableCollection<FlyThroughData> data;
        ObservableCollection<FlyThroughData> urlFlyThroughData; // fly through that was loaded from the URL (i.e. using bits after the #)

        ImageArranger arranger;
        SuperDeepZoom parent;

        public event EventHandler HashChanged;        

        public FlyThroughManager(ImageArranger arranger, SuperDeepZoom parent)
        {

            data = new ObservableCollection<FlyThroughData>();
            urlFlyThroughData = new ObservableCollection<FlyThroughData>();

            this.arranger = arranger;
            this.parent = parent;

            //Whenever the MIS changes this class will collect a new fly through point, assuming there
            //is no slideshow running
            arranger.ArrangeAnimationComplete += new EventHandler(arranger_ArrangeAnimationComplete);
            arranger.ViewedImageChanged += new EventHandler(arranger_ViewedImageChanged);

            parseHash();
        }

        /// <summary>
        /// Check for a fly through hash on the URL
        /// </summary>
        void parseHash()
        {
            if (!string.IsNullOrEmpty(HtmlPage.Window.CurrentBookmark))
            {
                string hash = HtmlPage.Window.CurrentBookmark;
                deserialiseFromHash(hash);
            }
        }

        /// <summary>
        /// Contains fly through data passed in from the URL
        /// </summary>
        public ObservableCollection<FlyThroughData> UrlFlyThroughData
        {
            get
            {
                return urlFlyThroughData;
            }
        }

        /// <summary>
        /// Contains the fly through data from the current users session
        /// </summary>
        public ObservableCollection<FlyThroughData> CurrentFlyThroughData
        {
            get
            {
                return data;
            }
        }

        /// <summary>
        /// If there was a fly through passed in through the URL
        /// </summary>
        public bool HasUrlFlyThrough
        {
            get
            {
                return UrlFlyThroughData != null && UrlFlyThroughData.Count > 1 ? true : false;
            }
        }

        /// <summary>
        /// Serialise the current walkthrough points in to a URL suitable format
        /// </summary>
        /// <returns></returns>
        string serialiseToHash()
        {
            string result = "";

            foreach (FlyThroughData w in data)
            {
                result += w.ImageId + ",";
            }

            return result.Trim(',');
        }

        /// <summary>
        /// Take a URL and deserialise back in to walkthrough data objects
        /// </summary>
        /// <param name="url"></param>
        private void deserialiseFromHash(string hash)
        {
            string[] parts = hash.Split(',');
            foreach (string part in parts)
            {
                int val;
                if (Int32.TryParse(part, out val))
                {
                    urlFlyThroughData.Add(new FlyThroughData(val));
                }
            }
        }

        /// <summary>
        /// Convert the currnet fly through to a URL #
        /// </summary>
        public string HashUrl
        {
            get
            {
                return serialiseToHash();
            }
        }

        #region EventHandlers
        void arranger_ArrangeAnimationComplete(object sender, EventArgs e)
        {
            //This only needs to be run after the very first animation change
            arranger.ArrangeAnimationComplete -= new EventHandler(arranger_ArrangeAnimationComplete);

            if (urlFlyThroughData != null && urlFlyThroughData.Count == 1)
            {
                arranger.DisplaySubImageCentered(urlFlyThroughData[0].ImageId, true);
            }
        }

        /// <summary>
        /// When ever the user selects a new image this will record that change
        /// so it may be serialised later in to the URL for sharing with others
        /// </summary>        
        void arranger_ViewedImageChanged(object sender, EventArgs e)
        {
            if (!parent.SlideshowRunning)
            {
                if (arranger.ViewedImage != null && arranger.ViewedImage.HasValue)
                {
                    int i = arranger.ViewedImage.Value;

                    //ensure the image does not already exist in the collection.
                    if (data.SingleOrDefault(p => p.ImageId == i) == null)
                    {
                        data.Add(new FlyThroughData(i));
                        if (HashChanged != null)
                        {
                            HashChanged(this, EventArgs.Empty);
                        }
                    }
                }
            }
        }
        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            if (arranger != null)
            {
                arranger.ArrangeAnimationComplete -= new EventHandler(arranger_ArrangeAnimationComplete);
                arranger.ViewedImageChanged -= new EventHandler(arranger_ViewedImageChanged);
            }
        }

        #endregion
    }
}